package gpip

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"syscall"
	"time"
)


// IpToInt
// @description: ip转int
// @param:
// @author: GJing
// @email: gjing1st@gmail.com
// @date: 2021/12/14 11:07
// @success:
func IpToInt(ip string) int64{
	ipArr := strings.Split(ip,".")
	_ = ipArr[3]
	ipInt0,_ := strconv.Atoi(ipArr[0])
	ipInt1,_ := strconv.Atoi(ipArr[1])
	ipInt2,_ := strconv.Atoi(ipArr[2])
	ipInt3,_ := strconv.Atoi(ipArr[3])
	return int64(ipInt0) << 24 + int64(ipInt1) << 16 + int64(ipInt2) << 8 +int64(ipInt3)
}

func IpToBytes(ip string) []byte{
	ipArr := strings.Split(ip,".")
	_ = ipArr[3]
	p := make([]byte,4)
	ipInt0,_ := strconv.Atoi(ipArr[0])
	ipInt1,_ := strconv.Atoi(ipArr[1])
	ipInt2,_ := strconv.Atoi(ipArr[2])
	ipInt3,_ := strconv.Atoi(ipArr[3])
	p[0] = byte(ipInt0)
	p[1] = byte(ipInt1)
	p[2] = byte(ipInt2)
	p[3] = byte(ipInt3)
	return p
}

func Int64ToIP(intIP int64) net.IP {
	var bytes [4]byte
	bytes[0] = byte(intIP & 0xFF)
	bytes[1] = byte((intIP >> 8) & 0xFF)
	bytes[2] = byte((intIP >> 16) & 0xFF)
	bytes[3] = byte((intIP >> 24) & 0xFF)

	return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])
}

type GeoLocation struct {
	Lat float64 `json:"lat"`
	Lng float64 `json:"lng"`
}

type QQIpLocation struct {
	Status  int    `json:"status"`
	Message string `json:"message"`
	Result  struct {
		Ip       string      `json:"ip"`
		Location GeoLocation `json:"location"`
		AdInfo   struct {
			Nation   string `json:"nation"`
			Province string `json:"province"`
			City     string `json:"city"`
			District string `json:"district"`
			AdCode   int    `json:"adcode"`
		} `json:"ad_info"`
	} `json:"result"`
}

// GetLocationFromQQ
// @description: 通过ip获取所在省市区
// @author: GJing
// @email: gjing1st@gmail.com
// @date: 2021/11/16 10:55
// @return:
func GetLocationFromQQ() (l *QQIpLocation, err error) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: tr,
		Timeout:   time.Second * 2,
	}
	req, err := http.NewRequest("GET", "https://apis.map.qq.com/ws/location/v1/ip?key=LSNBZ-WT2W3-XC23P-YTTOH-F2D73-W2F4R", nil)
	if err != nil {
		return
	}
	req.Header.Add("Referer", "https://prv.cartesianshield.com/ipquery.service")
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("getGeoLocation failed: %s\n", err)
		fmt.Printf("getGeoLocation failed: %s\n", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		log.Printf("getGeoLocation failed: status: %s\n", resp.Status)
		fmt.Printf("getGeoLocation failed: status: %s\n", resp.Status)
		err = syscall.ENODATA
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	loc := &QQIpLocation{}
	err = json.Unmarshal(body, loc)
	if err == nil {
		l = loc
	}
	return
}

//ExternalIP 判断局域网ip或者是否连接wifi插入网线
func ExternalIP() (net.IP, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		//fmt.Println(iface.Flags)
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		if len(strings.Split(iface.Name, "VMware")) > 1{
			//VMware虚拟机
			continue
		}
		//fmt.Println("======",iface)
		addrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			ip := getIpFromAddr(addr)
			if ip == nil {
				continue
			}
			return ip, nil
		}
	}
	return nil, errors.New("connected to the network?")
}

func getIpFromAddr(addr net.Addr) net.IP {
	var ip net.IP
	switch v := addr.(type) {
	case *net.IPNet:
		ip = v.IP
	case *net.IPAddr:
		ip = v.IP
	}
	if ip == nil || ip.IsLoopback() {
		return nil
	}
	ip = ip.To4()
	if ip == nil {
		return nil // not an ipv4 address
	}

	return ip
}
